package cn.jinjimi.app.managers.task;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * Created by lforxeverc on 2016/10/31.
 */

public abstract class BaseTaskPool<T extends BaseTask> implements TaskPool {
    private Stack<T> mTaskStack = new Stack<>();
    private List<IPoolChangeObserver> mObservers = new ArrayList<>();

    @Override
    public final synchronized T pop() {
        if (mTaskStack != null && !mTaskStack.isEmpty()) {
            T task = mTaskStack.pop();
            if (task != null && task.isExecuteAuto() && task.getTaskStatus() == BaseTask.TaskStatus.Pending) {
                task.setTaskStatus(BaseTask.TaskStatus.Running);
                task.run();
                task.setTaskStatus(BaseTask.TaskStatus.End);
            }
            return task;
        }
        return null;
    }

    @Override
    public BaseTask push(BaseTask task) {
        if (mTaskStack != null)
            mTaskStack.push((T) task);
        return task;
    }

    @Override
    public BaseTask cancel(BaseTask task) {
        if (mTaskStack != null) {
            mTaskStack.remove(task);
            task.setTaskStatus(BaseTask.TaskStatus.Cancel);
        }
        return task;
    }

    @Override
    public void cancelAll() {
        if (mTaskStack != null) {
            mTaskStack.clear();
        }
    }

    @Override
    public void addObserver(IPoolChangeObserver l) {
        if (mObservers != null && l != null) {
            mObservers.add(l);
        }
    }

    @Override
    public void removeObserver(IPoolChangeObserver l) {
        if (mObservers != null) {
            if (l != null) {
                mObservers.remove(l);
            } else {
                mObservers.clear();
            }
        }
    }

    @Override
    public void notifyAll(BaseTask task, boolean pushOrPop) {
        if (mObservers != null && !mObservers.isEmpty()) {
            for (IPoolChangeObserver l : mObservers)
                l.onChange(task, pushOrPop);
        }
    }

    public abstract String name();

}
